查看原文
其他

RecyclerView | 在 RecyclerView 中使用 ListAdapter

Android Android 开发者 2021-08-05
本文是介绍 RecyclerView 入门系列文章的第二篇。如果您已经对创建 RecyclerView 有了一定的认识,请继续阅读本文。如果尚未熟悉,建议您首先阅读本系列中的第一篇文章

RecyclerView 可以很高效地显示列表数据。对于静态的列表数据,默认的 adapter 足矣。然而,在多数情况下,RecyclerView 的数据是动态变化的。拿备忘工作的应用举例: 主要操作是添加新的工作事项,删除已经完成的工作事项。notifyItemInserted() 可以将新任务添加到指定位置,但是需要删除元素的时候问题就来了,notifyItemRemoved() 只有在您已知待删任务的位置时才有效果。虽然可以写代码来确定待删任务的位置,然后调用 notifyItemRemoved(),但是代码会变得非常繁杂。调用 notifyDataSetChanged() 也是一个办法,但是它会重绘整个视图,包括数据未发生变化的部分,使得该操作的代价变大。而 ListAdapter 可以处理元素的添加和删除而无需重绘视图,甚至可以为变化添加动画效果。

使用 ListAdapter 的另一个好处是: 当添加或删除元素的时候,还可以添加动画。这样用户可以很直观地看到列表数据的变化。虽然没有 ListAdapter 也可以实现动画效果,但是这就需要开发者自行实现,并且由于带有动画的视图需要重绘,所以无法达到同样的性能表现。

添加元素的动画效果



处理差异比较



DiffUtilListAdapter 能够高效改变元素的奥秘所在。DiffUtil 会比较新旧列表中增加、移动、删除了哪些元素,然后输出更新操作的列表将原列表中的元素高效地转换为新的元素。


为了能够识别新的数据,DiffUtil 需要您重写 areItemsTheSame()areContentsTheSame()areItemsTheSame() 检查两个元素是否为同一元素。areContentsTheSame() 检查两个元素是否包含相同的数据。

areItemsTheSame() 比较元素的示意图

areContentsTheSame() 比较元素的示意图
Adapter 类中添加 DiffUtil 对象,并且复写 areItemsTheSame()areContentsTheSame()
<!-- Copyright 2019 Google LLC. SPDX-License-Identifier: Apache-2.0 -->
object FlowerDiffCallback : DiffUtil.ItemCallback<Flower>() { override fun areItemsTheSame(oldItem: Flower, newItem: Flower): Boolean { return oldItem.id == newItem.id }
override fun areContentsTheSame(oldItem: Flower, newItem: Flower): Boolean { return oldItem == newItem }}

Adapter 的父类由 RecyclerView.Adapter 改为 ListAdapter,并传入 DiffCallback
<!-- Copyright 2019 Google LLC. SPDX-License-Identifier: Apache-2.0 -->
class FlowerAdapter : ListAdapter<String, FlowerAdapter.FlowerViewHolder>(FlowerDiffCallback)


更新列表



ListAdapter 通过 submitList() 方法获取数据,该方法提交了一个列表来与当前列表进行对比并显示。也就是说您无需再重写 getItemCount(),因为 ListAdapter 会负责管理列表。


  • ListAdapter

    https://developer.android.google.cn/reference/androidx/recyclerview/widget/ListAdapter

  • submitList()

    https://developer.android.google.cn/reference/androidx/recyclerview/widget/ListAdapter#submitList(java.util.List%3CT%3E)


Activity 类中,调用 AdaptersubmitList() 方法并传入数据列表。

<!-- Copyright 2019 Google LLC. SPDX-License-Identifier: Apache-2.0 -->
val flowerList = resources.getStringArray(R.array.flower_array).toMutableList()val flowerAdapter = FlowerAdapter()flowerAdapter.submitList(flowerList)

Adapter 类中,onBindViewHolder() 现在可以使用 getItem() 从数据列表中获取指定位置的元素了。


  • getItem()
    https://developer.android.google.cn/reference/androidx/recyclerview/widget/ListAdapter#getItem(int)


<!-- Copyright 2019 Google LLC. SPDX-License-Identifier: Apache-2.0 -->
override fun onBindViewHolder(holder: FlowerViewHolder, position: Int) { holder.bind(getItem(position))}

就这么简单。仅需几步简单操作就可以在您的 RecyclerView 中使用 ListAdapter。现在您的应用可以通过使用 ListAdapter 来更新那些发生变化的元素以获得更好的性能和用户体验了。



下一步



关于 ListAdapter 的完整示例代码都在这里


  • 完整示例代码
    https://github.com/android/views-widgets-samples/tree/main/RecyclerViewKotlin

感谢阅读 RecyclerView 系列的第二篇文章。请继续关注未来更多关于 RecyclerView 的内容。


如果您想了解更多关于 ListAdapter 的内容,请参考官方文档


  • 官方文档

    https://developer.android.google.cn/reference/androidx/recyclerview/widget/ListAdapter



 点击屏末 | 阅读原文 | 即刻了解更多关于 ListAdapter 的内容


推荐阅读

如页面未加载,请刷新重试


    您可能也对以下帖子感兴趣

    文章有问题?点此查看未经处理的缓存